#ifndef _VMDESCRIPTION_H_
#define	_VMDESCRIPTION_H_
/*------------------------------------------------------------
2008/5/18 By YPC
xMappingNode is of the new mapping node design (please see design document)
There is no more VVnode and WVnode in this new design.
"x" means X-man mapping node.
a xMappingNode can accept abitrary kinds of connections 
(from WOPs, VMs, collectors, or arithmetic operator
--------------------------------------------------------------
*/

#include <vector>
#include <memory>

enum MNClass {
	CLASS_REQUIRED = 0, // this parameters are major parameters and often need to be connected 
								  // to some variables. If not, the default values will be used 
	CLASS_DEFAULT = 1, // this parameter can be left alone but with default value
	CLASS_HIDDEN = 2,   // this parameter should not be shown to the user to connect
	CLASS_UNKNOWN = -1
};

enum MNCategory {
	CATEGORY_NAME = 0,		// this parameters are used to classify port, added by howway
	CATEGORY_POSITION = 1,
	CATEGORY_COLOR = 2,
	CATEGORY_SCALE = 3,
	CATEGORY_ROTATION = 4,
	CATEGORY_SIZE = 5,
	CATEGORY_OTHER = 6,
	CATEGORY_NO = 7,
	CATEGORY_UNKNOWN = -1
};

std::string CLASS_to_string( MNClass classtype ); // transfer class string to integer, when failed, return ""
MNClass string_to_CLASS( const std::string & classtype ); // transfer intger to class string, when failed, return -1 
std::string CATEGORY_to_string( MNCategory category );
MNCategory string_to_CATEGORY( const std::string & category );
std::string trf( const std::string & );					  // transfer "wop" "wops" to "var" "vars"

struct MNParameter {
	/// the string can be "int" "int*" "string" "string*" "vm" "vms" "wop" "wops"
	std::string type;
	/// the name of the parameter
	std::string name;
	/**
		can be
		DEFAULT - this port is by default
		REQUIRED - this port must be linked 
		HIDDEN   - special used by reference VM
	 */
	MNClass klass;
	// default value
	std::string defaultValue;
	// can be CATEGORY_NAME, CATEGORY_POSITION, CATEGORY_COLOR, CATEGORY_SCALE, CATEGORY_ROTATION, CATEGORY_SIZE, CATEGORY_OTHER
	MNCategory category;
};

struct vmdescriptor {
	std::string vm_name;
	std::string vm_description;
	std::string vm_category;
	std::string vm_type;// the type of vm. It can be "int" "bool" for PTVM "ref" for RTVM "composite" for CPVM
	std::string idname;
	int id;
	std::string compositebody_mds;

	std::vector< MNParameter > inputParameters;
	std::vector< MNParameter > outputParameters;
};

class vmLibrary {
public:
	static vmLibrary & instance();

	vmdescriptor* get_vmdescriptor( int id ) const;
	vmdescriptor* get_vmdescriptor( const std::string & idname ) const;
	int get_vm_total() const;
	const std::vector< MNParameter > & get_vm_default_input_parameters() const;
	const std::vector< MNParameter > & get_vm_default_output_parameters() const;
	int get_id_by_name( const std::string & name ) const;
	std::string get_name_by_id( int id ) const;

private:
	vmLibrary();
	vmLibrary( const vmLibrary & );
	vmLibrary & operator =( const vmLibrary & );
	/// destructor
	~vmLibrary();

	class Private;
	friend class Private;
	std::shared_ptr< Private > p_;
};

#endif 
